package cn.k7g.alloy.model;

/**
 * 排序用的序号类型, 支持js 数字类型,
 * 同时支持企业微信范围
 * 排序方式为正序
 *
 * 在 mybatis 类型中为 bigint
 * @author victor-wu
 * @date 2021/9/27 上午11:45
 */
public class SortOrder implements Comparable<SortOrder> {

    public static final long MAX_VALUE = 1L << 32;
    public static final long MIN_VALUE = 0;
    /**中位值, 用于初始化首个位序号*/
    public static final long MID_VALUE = 1L << 20;
    /**默认间隔值, 用于两个序号之间默认的间隔长度*/
    public static final long INTERVAL_VALUE = 10000;

    private final long value;


    public static final SortOrder MIN = new SortOrder(MIN_VALUE);
    public static final SortOrder MIDDLE = new SortOrder(MID_VALUE);


    public SortOrder() {
        this.value = 0;
    }

    public SortOrder(long value) {
        if (value > MAX_VALUE) {
            this.value = MAX_VALUE;
        } else if (value < MIN_VALUE) {
            this.value = MIN_VALUE;
        } else {
            this.value = value;
        }
    }




    public long longValue() {
        return this.value;
    }

    /**
     * 移动到指定位置
     * @param value
     * @return
     */
    public SortOrder move(long value) {
        return new SortOrder(this.value + value);
    }

    /**
     * 以当前 SortOrder 为开始， 传入end 结束点。
     * 将获取两个序号的中间值
     * @param end 结束的序号
     * @return 如果返回是null, 无法获取中间值，表示无效序号
     */
    public SortOrder moveBetween(SortOrder end) {
        long diff = Math.abs(this.longValue() - end.longValue());
        long newSort = diff / 2 + Math.min(this.longValue(), end.longValue());
        if (newSort == end.longValue() || newSort == this.longValue()) {
            return null;
        }
        return new SortOrder(newSort);
    }

    /**
     * 移动默认间隔顺序  增减序号
     * @return
     */
    public SortOrder moveIncreaseInterval() {
        return new SortOrder(this.value + INTERVAL_VALUE);
    }

    /**
     * 移动默认间隔顺序  减少序号
     * @return
     */
    public SortOrder moveDeductInterval() {
        return new SortOrder(this.value - INTERVAL_VALUE);
    }

    public boolean isMinimum() {
        return this.value == MIN_VALUE;
    }

    @Override
    public String toString() {
        return Long.toString(this.value);
    }

    @Override
    public int compareTo(SortOrder o) {
        // 倒序, 所以this 在后面
        return Long.compare(o.longValue(), this.value);
    }

    /**
     * 获取最小间隔数
     * @param size
     * @return
     */
    public long getMinimumAvailableInterval(int size) {
        long diff = (this.value - 1) / size;
        return diff > INTERVAL_VALUE ? INTERVAL_VALUE : diff;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null || !(obj instanceof SortOrder)) {
            return false;
        }
        SortOrder o = (SortOrder) obj;
        return o.value == o.value;
    }

    @Override
    public int hashCode() {
        return Long.hashCode(value);
    }
}


